package com.xiang.springboot.demo.thread.limit;

import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class ThreadService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadService.class);
    private final BlockingQueue<String> que = new LinkedBlockingQueue<>();// 待翻译的队列
    private final AtomicInteger threadCnt = new AtomicInteger(0);// 当前翻译中的线程数
    private final int maxThreadCnt = 2;// 允许同时执行的翻译线程数
    private static final int NUM_OF_EVERY_TIME = 50;// 每次提交的翻译条数

    public void saveAsync(String str) {
        LOGGER.debug("当前线程:" + Thread.currentThread().getName());
        offer(str);
        save();
    }

    private boolean offer(String str) {
        if (!que.contains(str)) {
            boolean result = que.offer(str);
            LOGGER.trace("[" + str + "]加入队列结果[" + result + "]，队列中数据总个数:" + que.size());
            return result;
        }
        return false;
    }

    private void save() {
        int cnt = threadCnt.incrementAndGet();// 当前线程数+1
        if (cnt > maxThreadCnt) {
            // 已启动的线程大于设置的最大线程数直接丢弃
            threadCnt.decrementAndGet();// +1的线程数再-回去
            return;
        }
        Thread thr = new Thread() {
            @Override
            public void run() {
                LOGGER.debug("线程[{}]开始运行。。。", Thread.currentThread().getName());
                long sleepTime = 30000L;
                boolean continueFlag = true;
                int maxContinueCnt = 3;// 最大连续休眠次数，连续休眠次数超过最大休眠次数后，while循环退出，当前线程销毁
                int continueCnt = 0;// 连续休眠次数
                while (continueFlag) {// 队列不为空时执行
                    if (Objects.isNull(que.peek())) {
                        try {
                            if (continueCnt > maxContinueCnt) {
                                // 连续休眠次数达到最大连续休眠次数，当前线程将销毁。
                                continueFlag = false;
                                continue;
                            }
                            // 队列为空，准备休眠
                            Thread.sleep(sleepTime);
                            continueCnt++;
                            continue;
                        } catch (InterruptedException e) {
                            // 休眠失败，无需处理
                            e.printStackTrace();
                        }
                    }
                    continueCnt = 0;// 重置连续休眠次数为0
                    List<String> params = new ArrayList<>();
                    que.drainTo(params, NUM_OF_EVERY_TIME);
                    LOGGER.debug("拿出数据[{}]", params.toString());
                }
                threadCnt.decrementAndGet();// 运行中的线程数-1
                distory();// 清理数据，必须放在方法最后，否则distory中的判断需要修改
            }

            /**
             * 如果是最后一个线程，清空队列和existsKey中的数据
             */
            private void distory() {
                LOGGER.debug("清理方法被调用...");
                if (0 == threadCnt.get()) {
                    // 最后一个线程退出时，执行清理操作
                    LOGGER.debug("执行线程清理操作,线程中剩余数据数:{}", que.size());
                    que.clear();
                }
            }
        };
//        thr.setDaemon(true);// 守护线程，如果主线程执行完毕，则此线程会自动销毁
        thr.setName("consumer:"+ RandomUtils.nextInt());
        thr.start();// 启动插入线程
    }

}
